<?php
/**
 * This file contains the class AlertsCheckModel which provides
 * most of the code requirements for the checking a submitted alert
 *
 * @copyright  2009 A Memory Tree
 * @license    A Memory Tree License
 * @version    $Id:$
 */
/*. require_module 'pcre'; .*/
define('ALLOWEMPTYALERTMATCH', TRUE);
define('DENYEMPTYALERTMATCH', FALSE);
/**
 * This class provides the code for checking alerts
 *
 * @copyright  2009 A Memory Tree
 * @license    A Memory Tree License
 * @version    Release: @package_version@
 */
class AlertsCheckModel
{
    /**
     * Access to the database methods
     *
     * @var AlertsCheckDB
     */
    private $_db;
    /**
     * Access to the view methods
     *
     * @var AlertsCheckView
     */
    private $_view;
    /**
     * Access to the Email methods
     *
     * @var EmailModel
     */
    private $_email;
    /**
     * Access to the Helper methods
     *
     * @var Helper
     */
    private $_helper;
    /**
     * Create a new instance of this class
     *
     * @param alertsCheckDB $db
     * @param alertsCheckView $view
     * @param EmailModel $email
     * @param Helper $helper
     */
    function __construct($db, $view, $email, $helper)
    {
        $this->_db = $db;
        $this->_view = $view;
        $this->_email = $email;
        $this->_helper = $helper;
    }
    /**
     * Check if an alerts parts match a person
     *
     * @return bool
     * @param array $alertParts
     * @param array $personParts
     * @param bool $allowEmptyMatch
     */
    function checkName($alertParts, $personParts, $allowEmptyMatch=FALSE) {
        $match = TRUE;
        foreach($alertParts as $value) {
            $alertPart = strval($value);
            $alertPartFound = FALSE;
            if ($match) {
                foreach($personParts as $value) {
                    $personPart = strval($value);
					if (
                        (strlen($alertPart) === 1 && stripos($personPart, $alertPart) === 0) // is Name Initial
                     || (strlen($alertPart) > 1 && stristr($personPart, $alertPart) !== FALSE) // is Partial Name
                    ) { 
                        $alertPartFound = TRUE;
                        unset($personParts[intval(array_search($personPart, $personParts))]);
                        break;
                    } else if ($allowEmptyMatch && empty($alertPart)) {
						$alertPartFound = TRUE;
					}
                }
            }
            $match = $alertPartFound;
        }
        return $match;
    }
    /**
     * Check if an alert matches the person
     *
     * The check needs to allow a partial alert match to be considered valid.
     * This is done by dividing the alert up in to its component parts, and checking if each part
     * of the alert is found anywhere in the person being matched.
     *
     * @return bool
     * @param array[string]string $alert
     * @param array[int]string &$personFirstNames
     * @param array[int]string &$personLastNames
     */
    function checkAlert($alert, &$personFirstNames, &$personLastNames) {
		$alertFirstNameParts = preg_split('/\\W/', $alert['firstName']);
        $alertLastNameParts = preg_split('/\\W/', $alert['lastName']);
        $personFirstNameParts = preg_split('/\\W/', implode(' ', $personFirstNames));
        $personLastNameParts = preg_split('/\\W/', implode(' ', $personLastNames));
        $firstNameMatch = $this->checkName($alertFirstNameParts, $personFirstNameParts, ALLOWEMPTYALERTMATCH);
        $lastNameMatch = $this->checkName($alertLastNameParts, $personLastNameParts, DENYEMPTYALERTMATCH);
        return $firstNameMatch === TRUE && $lastNameMatch === TRUE;
    }
    /**
     * Compare the alerts against the name
     *
     * @return array[int][string]string
     * @param array[int][string]string $alerts
     * @param array[string]string $person
     */
    function compareAlerts($alerts, $person)
    {
        $personFirstNames = array_filter(array($person['firstName'], $person['alsoKnownAs']));
        $personLastNames = array_filter(array($person['lastName'], $person['formerName'], $person['neeName']));
        $matchedAlerts = /*.(array[int][string]string).*/ array();
        foreach ($alerts as $alert) {
            if ($this->checkAlert($alert, $personFirstNames, $personLastNames)) {
                array_push($matchedAlerts, $alert);
            }
        }
        return $matchedAlerts;
    }
    /**
     * Send an email to the funeral home
     *
     * @return bool
     * @param string $emailAddress
     * @param string $subject
     * @param string $message
     */
    function sendEmail($emailAddress, $subject, $message)
    {
        $email = $this->_email;
        $email->setFromName('A Memory Tree Team');
        $email->setFromEmail('theteam@amemorytree.co.nz');
        $email->setToName($emailAddress);
        $email->setToEmail($emailAddress);
        $email->setSubject($subject);
        $email->setMessage($message);
        return $email->send();
    }
    /**
     * Notify a user about matching alerts
     *
     * @return bool
     * @param int $userId
     * @param array[int][string]string $matches
     * @param int $personId
     * @param array[string]string $person
     */
    function notifyUser($userId, $matches, $personId, $person)
    {
		$helper = $this->_helper;
        $db = $this->_db;
        $view = $this->_view;
        $email = $db->getEmail($userId);
        $listOfPeople = array('');
		$expiryDateOption = '';
        foreach ($matches as $index => $alert) {
            array_push($listOfPeople, $view->person($alert['firstName'], $alert['lastName']));
            $time = strtotime($alert['purchased']);
            $expiryDateOption = ' on ' . date('d M Y', $helper->changeTime($time, 1));
        }
        if (count($listOfPeople) > 1) {
            $firstName = $person['firstName'];
            $lastName = $person['lastName'];
            $fullName = $firstName.' '.$lastName;
            array_push($listOfPeople, '');
            $people = implode(' | ', $listOfPeople);
            $subject = $view->subject($people);
            $message = $view->message($personId, $fullName, $people, $expiryDateOption);
            $emailSuccess = $this->sendEmail($email, $subject, $message);
        }
        return $emailSuccess;
    }
    /**
     * Notify users about their potential matches
     *
     * @return void
     * @param int $personId
     * @param array[int][string]string $alerts
     * @param array[string]string $person
     */
    function notifyUsers($personId, $alerts, $person)
    {
        $db = $this->_db;
        $userAlerts = array();
        $userEmail = array();
        foreach ($alerts as $alertsKey => $alert) {
            $index = intval($alertsKey);
            $userId = intval($alert['userId']);
            $email = $alert['email'];
            if (empty($userAlerts[$userId])) {
                $userAlerts[$userId] = array($index);
            } else {
                array_push($userAlerts[$userId], $index);
            }
            $userEmail[$userId] = $email;
        }
        foreach ($userAlerts as $userKey => $alertList) {
            $userId = intval($userKey);
            if (!empty($userId)) {
                $matches = /*.(array[int][string]string).*/ array();
                foreach ($alertList as $index) {
                    $alert = $alerts[$index];
                    array_push($matches, $alert);
                }
                if ($this->notifyUser($userId, $matches, $personId, $person)) {
                    foreach ($matches as $alert) {
						$alertId = intval($alert['alertId']);
                        $db->setPersonAlert($personId, $alertId);
                    };
                }
           }
        }
    }
    /**
     * Check if the name has an alert for it
     *
     * @return bool
     * @param int $personId
     */
    function check($personId)
    {
        $db = $this->_db;
        $person = $db->getPerson($personId);
        $alerts = $db->getUnemailedPaidAlerts($personId);
        $alerts = $this->compareAlerts($alerts, $person);
        $this->notifyUsers($personId, $alerts, $person);
    }
}
?>
